const MsgDownloader = {
  get error() { return -1; }, // 出现错误
  get fileInfo() { return 0; }, // 获取文件信息 保持与初始化一致,因为下一步就是初始化
  get download() { return 1; }, // 下载文件
  get dataIn() { return 2; }, // 数据到达
};
function typeFileList(i, url, tStart, tEnd) {
  return {
    sn: i,
    url: url,
    start: tStart,
    end: tEnd,
    duration: tEnd - tStart,
    // da: true
  };
}
DataView.prototype.m3u8 = function (prefix, n) {
  let i = 0;
  let j = 0;
  let s = 0;
  let u = 0;
  let ret = [];
  let t = "#EXTINF:";
  let siz = [];
  let ss = 0;
  while (u < t.length) {
    siz.push(t.charCodeAt(u++));
  }
  while (i < this.byteLength) {
    t = this.getUint8(i++);
    if (j < siz.length) {
      if (t == siz[j]) j++; else j = 0;
    } else {
      if (t == 10) {
        j = 0;
        u = "";
        ss = ret.length ? ret[ret.length - 1].end : 0;
        s = parseFloat(s) + ss;
        while (i < this.byteLength) {
          t = this.getUint8(i++);
          if (t == 10) {
            if (prefix && u.indexOf("http://") < 0 && u.indexOf("https://") < 0) u = prefix + u;
            ret.push(typeFileList(ret.length, u, ss, s));
            s = "";
            break;
          }
          u += String.fromCharCode(t);
        }
      } else {
        s += String.fromCharCode(t);
      }
    }
  }
  return ret;
};
DataView.prototype.getStr = function (start, end) {
  if (typeof start == 'undefined' || start < 0) start = 0;
  if (!end || end < 0) end = this.byteLength;
  else if (end <= start) end = start + end;

  let ret = '';
  let t = 1;
  while (start < end && t) {
    t = this.getUint8(start++);
    ret += String.fromCharCode(t);
  }
  return ret;
};

function Downloader() {
  this.ws = null;
}


Downloader.prototype.getFileInfo = function (p) {
  if (p.isM3u8 || p.url.lastIndexOf(".m3u8") > 0) {
    let t = typeFileList(p.sn, p.url);
    this.downloadFile(t, (res) => {
      p.list = new DataView(res).m3u8(p.url.substr(0, p.url.lastIndexOf("/") + 1), p.n);
      if (!Array.isArray(p.list)) p.list = [];
      self.postMessage(p, [res]);
    });
    return;
  }
  let xhr = new XMLHttpRequest();
  xhr.open('get', p.url, true);
  xhr.onreadystatechange = () => {
    let t = parseInt(xhr.getResponseHeader("Content-Length"));
    if (t > 0) {
      xhr.abort();
      p.size = t;
      p.list = [typeFileList(p.sn, p.url)];
      this.downloadFile(p.list[0], (data, p) => {
        p.list[0].d = data;
        let t = '';
        let d = new DataView(data);
        let l = 0;
        let o = 0;
        let m = d.byteLength - 8;
        do {
          l = d.getUint32(o);
          t = d.getStr(o + 4, 4);
          o += l;
        } while (o < m && t != "moov");
        m = p.chunk;
        if (t == "moov") {
          p.list.push(typeFileList(p.sn, p.url));
          l = parseInt((p.size - o) / m);
          d = o;
        } else {
          l = parseInt((o - m) / m) + 1;
          d = m;
          p.last = 1;
        }
        o = p.list.length;
        while (l--) {
          p.list.push(typeFileList(p.sn, p.url));
          d += m;
        }
        p.list[o - 1].info.file.end = "";
        self.postMessage(p, [data]);
      }, p);
    }
  };
  xhr.send();
};
Downloader.prototype.downloadFile = function (p, c, cp) {
  if (!p.url) {
    p.url = p._url;
  }
  let xhr = new XMLHttpRequest;
  xhr.open('get', p.url, true);
  xhr.responseType = 'arraybuffer';
  if (p.info && p.info.file && p.info.file.end) xhr.setRequestHeader("Range", "bytes=" + p.info.file.start + "-" + p.info.file.end);
  xhr.onload = function () {
    if (c) {
      c(xhr.response, cp);
      return;
    }
    if (p.info && p.info.file) p.info.file.end = p.info.file.start + parseInt(xhr.getResponseHeader("Content-Length")) - 1;
    // p.d = new Uint8Array(xhr.response);
    p.d = xhr.response;
    // console.log(xhr);
    self.postMessage(p, [p.d]);
  };
  xhr.send();
};


self.downloader = new Downloader();
if (!self.downloader) console.error("Downloader not initialized!");
self.onmessage = function (evt) {
  switch (evt.data.e) {
    case MsgDownloader.fileInfo:
      self.downloader.getFileInfo(evt.data);
      break;
    case MsgDownloader.download:
      self.downloader.downloadFile(evt.data);
      break;
    default:
      console.warn("UnSupport messsage ", evt.data);
  }
};